home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Pascal Super Library
/
Pascal Super Library (CW International)(1997).bin
/
LIBRARY
/
PAS_0693
/
RKEYINT.TXT
< prev
next >
Wrap
Text File
|
1993-06-28
|
12KB
|
273 lines
─ Fido Pascal Conference ────────────────────────────────────────────── PASCAL ─
Msg : 425 of 474
From : Lou Duchez 1:157/200.0 21 Jun 93 21:16
To : Ian Lin
Subj : Using esc key
────────────────────────────────────────────────────────────────────────────────
Since you seem to be talking about multiple key presses, let me repost:
HOW TO RESET YOUR KEYBOARD INTERRUPT TO READ MULTIPLE KEYS
- by Lou DuChez
When you press/release a key on the keyboard, the "scan code" of the key
is sent to port 60h of your machine (bit 0-6 specify the key; bit 7
indicates a "press" with a "0" and a release with a "1"). This triggers
hardware interrupt 09h, which triggers other software interrupts and
puts the appropriate keystrokes into your keyboard buffer. Ideally,
you'd like to be able to read port 60h directly to get keyboard status,
but unfortunately the port is reinitialized to "0" in the course of all
those interrupts. So what you need to do is modify the hardware
interrupt to record which keys are up/down before any of the
"housekeeping" can occur.
To do this, the steps you'll need to do are:
1) Store the location of the "normal" interrupt 09h routine. Declare a
pointer variable called "OLDKBDINT", and execute this command:
getintvec($09, oldkbdint); { make sure you've got "Uses DOS"! }
2) Write a simple interrupt handler. Just something to keep track of
what keys are down. We'll keep track of them all with an
"array [0..127] of boolean" called "KeyDown". Declare this array,
and be sure to initialize it to all "false" before using it. (At
the end of this message, I'll list the various "scan codes" for the
various keys. Be patient.) Here's the new keyboard handler:
procedure newkbdint; interrupt;
begin
keydown[port[$60] mod 128] := (port[$60] < 128);
runproc(oldkbdint);
mem[$0040:$001a] := mem[$0040:$001c];
inline($fb);
end;
Explanations:
- The directive "Interrupt" is necessary so that the compiler
processes this procedure properly.
- The "KeyDown" line: whichever key is specified in the keyboard
port, is "pressed" if the high bit is "0" and "released" if the
high bit is "1".
- RunProc: After reading the port, we want to process the keystroke
in the "normal" way. So we "run" the "normal" keyboard interrupt
routine via "RunProc". RunProc is a procedure that I cribbed from
"Turbo Pascal 6.0: The Complete Reference" by Stephen O'Brien, and
you really need it. Anyway, it goes like this:
procedure runproc(proctorun: pointer);
begin
inline($9c/ { PUSHF }
$ff/$5e/$06); { CALL DWORD PTR [BP+6] }
end;
- The "Mem" line clears the keyboard buffer. The one memory
location points to the first unread character in the buffer, and
the other points to the very last one. By setting them equal,
the computer is fooled into thinking that the keystroke has been
read. (This way, your computer won't beep incessantly after 16
keystrokes.)
- InLine: I'm calling the STI instruction ("Set Interrupt Flag") to
make sure the system will be able to read hardware interrupts.
(Not that I turned it "off" anywhere, but a little paranoia never
hurt anyone ...)
Notice that I don't do much in my interrupt handler except play with
memory. That makes it a pretty "crash-proof" animal. Notice also
that "my" routine executes first, reading the port before that info
can be lost; then, after the "normal" interrupt has had its fun, I
do the "postprocessing" of clearing the keyboard buffer.
3) To invoke this new interrupt handler:
setintvec($09, addr(newkbdint));
inline($fb); { another STI for good luck }
4) To reset the old interrupt handler when you end your program:
setintvec($09, oldkbdint);
inline($fb); { yet another STI: couldn't hurt, right? }
* * * C O N T I N U E D T O N E X T M E S S A G E * * *
---
* KingQWK 1.00 * As-Easy-As - the ONLY spreadsheet - download it today!
--- FidoPCB v1.4 beta
* Origin: PC-OHIO - The Best BBS in America (pcohio.com) (1:157/200)
─ Fido Pascal Conference ────────────────────────────────────────────── PASCAL ─
Msg : 426 of 474
From : Lou Duchez 1:157/200.0 21 Jun 93 21:16
To : Ian Lin
Subj : Using esc key {2}
────────────────────────────────────────────────────────────────────────────────
* * * C O N T I N U E D F R O M L A S T M E S S A G E * * *
Congratulations, you now have a new keyboard handler. The whole animal
should look something like this:
Program FlamingCarrotRules;
uses Dos;
var keydown: array [0..127] of boolean;
oldkbdint: pointer;
cnter: byte; { just a dumb "counter" variable }
{$F+} { Far calls for this "interrupt" stuff! }
procedure runproc();
.
.
procedure newkbdint; interrupt;
.
.
begin { main program }
for cnter := 0 to 127 do keydown[cnter] := false;
getintvec($09, oldkbdint);
setintvec($09, addr(newkbdint));
inline($fb);
.
. { Your code goes here; instead of reading the keyboard buffer, }
. { you check what keys are down via "KeyDown". }
.
setintvec($09, oldkbdint);
inline($fb);
end.
All of this makes a very nice unit, by the way. (Just don't try to
install the "new" interrupt in the initialization part of the unit: the
system doesn't like that.)
Another point to consider: a "Ctrl-Break" could cause your program to
pop to DOS before you have a chance to restore the "normal" keyboard
handler. Bad juju all around. Two approaches: 1) use CRT and set
"CheckBreak" to false; or 2) write an interrupt handler for "Ctrl-Break"
(interrupt 1bh). I leave it up to you to set it up. (Hint: it's very
much like the above, except that your new handler should contain NO
instructions -- so the system does NOTHING on a "Ctrl-Break" -- except
maybe another STI ...)
Finally, the scan codes (so you can actually make heads or tails of
"KeyDown"). First some constants for "special" keys.
const escscan: byte = $01; backscan: byte = $0e;
ctrlscan: byte = $1d; lshscan: byte = $2a;
capscan: byte = $3a; f1scan: byte = $3b;
f2scan: byte = $3c; f3scan: byte = $3d;
f4scan: byte = $3e; f5scan: byte = $3f;
f6scan: byte = $40; f7scan: byte = $41;
f8scan: byte = $42; f9scan: byte = $43;
f10scan: byte = $44; f11scan: byte = $d9;
f12scan: byte = $da; scrlscan: byte = $46;
tabscan: byte = $0f; entscan: byte = $1c;
rshscan: byte = $36; prtscan: byte = $37;
altscan: byte = $38; homescan: byte = $47;
upscan: byte = $48; pgupscan: byte = $49;
minscan: byte = $4a; leftscan: byte = $4b;
midscan: byte = $4c; rightscan: byte = $4d;
plusscan: byte = $4e; endscan: byte = $4f;
downscan: byte = $50; pgdnscan: byte = $51;
insscan: byte = $52; delscan: byte = $53;
numscan: byte = $45;
Is the "middle key" (the "5") on the keyboard being pressed? Only if
KeyDown[midscan] is "True". A couple mnemonics that might not be clear:
minscan = "the minus sign on the keypad"
midscan = "the middle ('5') key on the keypad"
plusscan = "the plus sign on the keypad"
lshscan = "the left shift key"
rshscan = "the right shift key"
entscan = "the enter key"
In my programs, I set up an array called "ScanOf": it's an
"array[' '..'~'] of byte" that returns the scan code of a key.
("What's the scan code of 'P'?" ScanOf['P']. "Is '3' currently being
pressed?" Only if KeyDown[ScanOf['3']] is "True".) Here are the
values:
* * * C O N T I N U E D T O N E X T M E S S A G E * * *
---
* KingQWK 1.00 * As-Easy-As - the ONLY spreadsheet - download it today!
--- FidoPCB v1.4 beta
* Origin: PC-OHIO - The Best BBS in America (pcohio.com) (1:157/200)
─ Fido Pascal Conference ────────────────────────────────────────────── PASCAL ─
Msg : 429 of 474
From : Lou Duchez 1:157/200.0 21 Jun 93 21:50
To : Ian Lin
Subj : Using esc key {3}
────────────────────────────────────────────────────────────────────────────────
** CONTINUED FROM A COUPLE MESSAGES AGO -- SCAN CODES!!
scanof['!'] := $02; scanof['1'] := $02;
scanof['@'] := $03; scanof['2'] := $03;
scanof['#'] := $04; scanof['3'] := $04;
scanof['$'] := $05; scanof['4'] := $05;
scanof['%'] := $06; scanof['5'] := $06;
scanof['^'] := $07; scanof['6'] := $07;
scanof['&'] := $08; scanof['7'] := $08;
scanof['*'] := $09; scanof['8'] := $09;
scanof['('] := $0a; scanof['9'] := $0a;
scanof[')'] := $0b; scanof['0'] := $0b;
scanof['_'] := $0c; scanof['-'] := $0c;
scanof['+'] := $0d; scanof['='] := $0d;
scanof['Q'] := $10; scanof['q'] := $10;
scanof['W'] := $11; scanof['w'] := $11;
scanof['E'] := $12; scanof['e'] := $12;
scanof['R'] := $13; scanof['r'] := $13;
scanof['T'] := $14; scanof['t'] := $14;
scanof['Y'] := $15; scanof['y'] := $15;
scanof['U'] := $16; scanof['u'] := $16;
scanof['I'] := $17; scanof['i'] := $17;
scanof['O'] := $18; scanof['o'] := $18;
scanof['P'] := $19; scanof['p'] := $19;
scanof['{'] := $1a; scanof['['] := $1a;
scanof['}'] := $1b; scanof[']'] := $1b;
scanof['A'] := $1e; scanof['a'] := $1e;
scanof['S'] := $1f; scanof['s'] := $1f;
scanof['D'] := $20; scanof['d'] := $20;
scanof['F'] := $21; scanof['f'] := $21;
scanof['G'] := $22; scanof['g'] := $22;
scanof['H'] := $23; scanof['h'] := $23;
scanof['J'] := $24; scanof['j'] := $24;
scanof['K'] := $25; scanof['k'] := $25;
scanof['L'] := $26; scanof['l'] := $26;
scanof[':'] := $27; scanof[';'] := $27;
scanof['"'] := $28; scanof[''''] := $28;
scanof['~'] := $29; scanof['`'] := $29;
scanof['|'] := $2b; scanof['\'] := $2b;
scanof['Z'] := $2c; scanof['z'] := $2c;
scanof['X'] := $2d; scanof['x'] := $2d;
scanof['C'] := $2e; scanof['c'] := $2e;
scanof['V'] := $2f; scanof['v'] := $2f;
scanof['B'] := $30; scanof['b'] := $30;
scanof['N'] := $31; scanof['n'] := $31;
scanof['M'] := $32; scanof['m'] := $32;
scanof['<'] := $33; scanof[','] := $33;
scanof['>'] := $34; scanof['.'] := $34;
scanof['?'] := $35; scanof['/'] := $35;
scanof[' '] := $39;
I hope I have managed to explain this well -- I never can tell. But it
does work, and I hope you enjoy it. I'd be eager for feedback; I intend
to keep posting this whenever anyone has questions about the keyboard,
and I want it to be as clear as possible. (And all of you out there:
if you think this message will help someone else, feel free to repost it
at will!)
---
* KingQWK 1.00 * As-Easy-As - the ONLY spreadsheet - download it today!
--- FidoPCB v1.4 beta
* Origin: PC-OHIO - The Best BBS in America (pcohio.com) (1:157/200)